package Proj_pack;

public class Worker implements Runnable{

	@Override
	public void run() {
		while (!Thread.interrupted() && netz2135.queueSwitcher.isAlive()){
			boolean brk = false;
			Mash aktMash = null;
				aktMash = netz2135.unstable.poll();
			if(aktMash == null)	{
				netz2135.switchWait.countDown();
				boolean b=false; do{	b=false;
				try {netz2135.nextGenWait.await();}catch(InterruptedException e1){b=true;}
				}while(b);
//				System.err.println("switcher alive? :"+ netz2135.queueSwitcher.isAlive());
				continue;
			}
			//erstellt ein int[] als kopie representation der knoten des splitters - wartet auf lock von aktMash - da wir sonst noch kein lock haben gibts kein hold-and-wait
			int[] splitter = aktMash.getSplitter(); 

			for(Knoten aktKnoten:aktMash.getkList()){ //lock auf aktmash war wieder offen, aktmash kann aber nur kleiner geworden sein
				if (brk) break;
				for(Knoten preKnoten : aktKnoten.getVorganger()){ //ueber alle vorganger ohne locks
					if (brk) break;
					boolean neuAnders = false;
					Mash neu = null;
					Mash preMash = preKnoten.tryGetMash(); //versucht das lock und die mashe von vorgangerknoten zu holen, wenn das lock nicht frei ist ist mash=null
					if (preMash!=null){ //wenn wir das lock auf preMash nicht bekommen haben brechen wir alles ab.
						try{
							neu = new Mash(preMash.getCap(), true);// wird noch nicht zu unstabel gemacht und lock geholt.
							try{
								for(Knoten knotenAusVorMash: preMash.getkList()){ //alle knoten aus preMash in neu verschieben, die nicht auf spliter zeigen
									if(!knotenAusVorMash.zeigtAufSpliter(splitter)){
										knotenAusVorMash.changeMash(neu); //verschieben braucht locks von preMash und neu
									}
								}
								if(!neu.getkList().isEmpty()) neuAnders=true; //mit neuAnders merken wir uns, ob wir knoten in neu verschoben haben, wobei neu noch gelockt sein muss
							}finally{
								neu.lock.unlock(); //neu freigeben
							}
						}finally{
							preMash.lock.unlock();  //wenn wir auf preMash arbeiten wollten sind wir jetzt fertig
						}
						if (neuAnders){	//wird nur ausgefuert wenn wir preMash geteilt haben
							netz2135.maschen.add(neu);
							netz2135.unstable.add(neu);	// die beiden bearbeiteten mashen als spliter in die unstable-queue
							netz2135.unstable.add(preMash); //irgendwie ist alles schneller wenn wir addFirst anstelle von addLast benutzen (???)
						}

					}else{
						brk = true;
						netz2135.unstable.add(aktMash);
						break;
					}
				}
			}
		}
//		System.err.println("worker down!!");
		netz2135.resultWait.countDown();
	}
}
